﻿#include "box_config_impl.hh"
#include "box/service_box.hh"
#include "kconfig/interface/config.h"
#include "kconfig/interface/config_factory.h"
#include "lang_impl.hh"
#include "src/kconfig/internal/bool_impl.h"
#include "src/kconfig/internal/domain.h"
#include "src/kconfig/internal/null_impl.h"
#include "src/kconfig/internal/number_impl.h"
#include "src/kconfig/internal/string_impl.h"
#include "util/module_loader/module_loader.hh"
#include "util/os_util.hh"
#include "util/string_util.hh"

#include <filesystem>
#include <functional>
#include <iostream>

namespace kratos {
namespace config {

/**
 * 配置属性名
 */
struct AttrName {
  constexpr static const char *LISTENER_HOST = "listener.host";
  constexpr static const char *LISTENER_TYPE = "listener.type";
  constexpr static const char *SERVICE_FINDER_TYPE = "service_finder.type";
  constexpr static const char *SERVICE_FINDER_HOSTS = "service_finder.hosts";
  constexpr static const char *BOX_CHANNEL_RECV_BUFFER_LEN =
      "box_channel_recv_buffer_len";
  constexpr static const char *BOX_NAME = "box_name";
  constexpr static const char *LOGGER_CONFIG_LINE = "logger_config_line";
  constexpr static const char *SERVICE_SERVICE_DIR = "service.service_dir";
  constexpr static const char *SERVICE_PRELOAD_SERVICE =
      "service.preload_service";
  constexpr static const char *SERVICE_AUTO_LOAD_SERVICE =
      "service.auto_load_service";
  constexpr static const char *CONNECT_OTHER_BOX_TIMEOUT =
      "connect_other_box_timeout";
  constexpr static const char *SERVICE_FINDER_CONNECT_TIMEOUT =
      "service_finder_connect_timeout";
  constexpr static const char *NECESSARY_SERVICE = "necessary_service";
  constexpr static const char *OPEN_COROUTINE = "open_coroutine";
  constexpr static const char *SERVICE_REMOTE_SERVICE_REPO_VERSION_API =
      "service.remote_service_repo_version_api";
  constexpr static const char *SERVICE_REMOTE_SERVICE_REPO_DIR =
      "service.remote_service_repo_dir";
  constexpr static const char *SERVICE_REMOTE_SERVICE_REPO_LATEST_VERSION_API =
      "service.remote_service_repo_latest_version_api";
  constexpr static const char *SERVICE_IS_OPEN_REMOTE_UPDATE =
      "service.is_open_remote_update";
  constexpr static const char *SERVICE_REMOTE_REPO_CHECK_INTERVAL =
      "service.remote_repo_check_interval";
  constexpr static const char *SERVICE_IS_START_AS_DAEMON =
      "service.is_start_as_daemon";
  constexpr static const char *HTTP_HTTP_MAX_CALL_TIMEOUT =
      "http.http_max_call_timeout";
  constexpr static const char *STATISTICS_IS_OPEN_RPC_STAT =
      "statistics.is_open_rpc_stat";
  constexpr static const char *OPEN_TRACE = "open_trace";
  constexpr static const char *MODULE_MODULE_DIR = "module.module_dir";
  constexpr static const char *LIMIT = "limit";
  constexpr static const char *LIMIT_OPEN_LIMIT = "limit.open_limit";
  constexpr static const char *SERVICE_FINDER_VERSION =
      "service_finder.version";
  constexpr static const char *OPEN_RPC_TIMEOUT = "open_rpc_timeout";
};

BoxConfigImpl::BoxConfigImpl(kratos::service::ServiceBox *box) { box_ = box; }

BoxConfigImpl::~BoxConfigImpl() {}

auto BoxConfigImpl::load(const std::string &config_file_path,
                         std::string &error) -> bool {
  config_.reset(ConfigFactory::createConfig());
  config_file_path_ = config_file_path;
  try {
    register_config_function();
    register_config_variable();
    config_->load("", config_file_path);
  } catch (std::exception &ex) {
    error = ex.what();
    return false;
  }
  if (config_->has(AttrName::LISTENER_HOST)) {
    auto *listener_list_array = config_->array(AttrName::LISTENER_HOST);
    for (int i = 0; i < listener_list_array->getSize(); i++) {
      auto host = listener_list_array->string(i)->get();
      std::string ip;
      std::string port;
      if (!util::get_host_config(host, ip, port)) {
        return false;
      }
      if (port == "*") {
        static const int START_PORT = 15000;
        static const int END_PORT = 18000;
        auto random_port = util::get_any_port(START_PORT, END_PORT);
        if (!random_port) {
          return false;
        }
        host = util::replace(host, "*", std::to_string(random_port));
        is_lock_config_ = false;
      }
      listener_list_.push_back(host);
    }
    if (listener_list_.empty()) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::LISTENER_HOST);
      }
      return false;
    }
  }
  if (config_->has(AttrName::LISTENER_TYPE)) {
    listener_host_type_ = config_->string(AttrName::LISTENER_TYPE)->get();
  }
  if (config_->has(AttrName::SERVICE_FINDER_TYPE)) {
    finder_type_ = config_->string(AttrName::SERVICE_FINDER_TYPE)->get();
    if (finder_type_.empty()) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::SERVICE_FINDER_TYPE);
      }
      return false;
    }
  }
  if (config_->has(AttrName::SERVICE_FINDER_HOSTS)) {
    finder_hosts_ = config_->string(AttrName::SERVICE_FINDER_HOSTS)->get();
    if (finder_hosts_.empty()) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::SERVICE_FINDER_HOSTS);
      }
      return false;
    }
  }
  if (config_->has(AttrName::BOX_CHANNEL_RECV_BUFFER_LEN)) {
    box_channel_recv_buffer_len_ = static_cast<int>(
        config_->getInt32(AttrName::BOX_CHANNEL_RECV_BUFFER_LEN));
    if (box_channel_recv_buffer_len_ <= 0) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::BOX_CHANNEL_RECV_BUFFER_LEN);
      }
      return false;
    }
  }
  if (config_->has(AttrName::BOX_NAME)) {
    box_name_ = config_->string(AttrName::BOX_NAME)->get();
    if (box_name_.empty()) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::BOX_NAME);
      }
      return false;
    }
  }
  if (config_->has(AttrName::LOGGER_CONFIG_LINE)) {
    logger_config_line_ = config_->string(AttrName::LOGGER_CONFIG_LINE)->get();
    if (logger_config_line_.empty()) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::LOGGER_CONFIG_LINE);
      }
      return false;
    }
  }
  if (config_->has(AttrName::SERVICE_SERVICE_DIR)) {
    service_dir_ = config_->string(AttrName::SERVICE_SERVICE_DIR)->get();
  }
#ifndef DISABLE_SB_CODE
  if (config_->has(AttrName::SERVICE_AUTO_LOAD_SERVICE)) {
    is_auto_load_service_ =
        config_->boolean(AttrName::SERVICE_AUTO_LOAD_SERVICE)->get();
    if (is_auto_load_service_) {
      find_all_services();
    }
  }
#endif
  if (config_->has(AttrName::SERVICE_PRELOAD_SERVICE)) {
    auto *preload_service_table =
        config_->table(AttrName::SERVICE_PRELOAD_SERVICE);
    while (preload_service_table->hasNext()) {
      auto *pair = preload_service_table->next();
      service_map_[pair->key()] = pair->value()->string()->get();
    }
  }
  if (config_->has(AttrName::CONNECT_OTHER_BOX_TIMEOUT)) {
    connect_other_box_timeout_ = static_cast<int>(
        config_->getInt32(AttrName::CONNECT_OTHER_BOX_TIMEOUT));
    if (connect_other_box_timeout_ <= 0) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::CONNECT_OTHER_BOX_TIMEOUT);
      }
      return false;
    }
  }
  if (config_->has(AttrName::SERVICE_FINDER_CONNECT_TIMEOUT)) {
    service_finder_connect_timeout_ = static_cast<int>(
        config_->getUint32(AttrName::SERVICE_FINDER_CONNECT_TIMEOUT));
    if (service_finder_connect_timeout_ <= 0) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::SERVICE_FINDER_CONNECT_TIMEOUT);
      }
      return false;
    }
  }
  if (config_->has(AttrName::NECESSARY_SERVICE)) {
    auto *services = config_->array(AttrName::NECESSARY_SERVICE);
    for (int i = 0; i < services->getSize(); i++) {
      necessary_service_.push_back(services->string(i)->get());
    }
  }
  if (config_->has(AttrName::OPEN_COROUTINE)) {
    if (config_->get(AttrName::OPEN_COROUTINE)->isString()) {
      is_open_coroutine_ =
          config_->string(AttrName::OPEN_COROUTINE)->get() == "true";
    } else {
      is_open_coroutine_ = config_->boolean(AttrName::OPEN_COROUTINE)->get();
    }
  }
  if (config_->has(AttrName::SERVICE_REMOTE_SERVICE_REPO_VERSION_API)) {
    remote_service_repo_version_api_ =
        config_->string(AttrName::SERVICE_REMOTE_SERVICE_REPO_VERSION_API)
            ->get();
  }
  if (config_->has(AttrName::SERVICE_REMOTE_SERVICE_REPO_DIR)) {
    remote_service_repo_dir_ =
        config_->string(AttrName::SERVICE_REMOTE_SERVICE_REPO_DIR)->get();
  }
  if (config_->has(AttrName::SERVICE_REMOTE_SERVICE_REPO_LATEST_VERSION_API)) {
    remote_service_repo_latest_version_api_ =
        config_
            ->string(AttrName::SERVICE_REMOTE_SERVICE_REPO_LATEST_VERSION_API)
            ->get();
  }
  if (config_->has(AttrName::SERVICE_IS_OPEN_REMOTE_UPDATE)) {
    if (config_->get(AttrName::SERVICE_IS_OPEN_REMOTE_UPDATE)->isString()) {
      is_open_remote_update_ =
          (config_->string(AttrName::SERVICE_IS_OPEN_REMOTE_UPDATE)->get() ==
           "true");
    } else {
      is_open_remote_update_ =
          config_->boolean(AttrName::SERVICE_IS_OPEN_REMOTE_UPDATE)->get();
    }
  }
  if (config_->has(AttrName::SERVICE_REMOTE_REPO_CHECK_INTERVAL)) {
    remote_repo_check_interval_ = static_cast<int>(
        config_->getInt32(AttrName::SERVICE_REMOTE_REPO_CHECK_INTERVAL));
    if (remote_repo_check_interval_ <= 0) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::SERVICE_REMOTE_REPO_CHECK_INTERVAL);
      }
      return false;
    }
  }
  if (config_->has(AttrName::SERVICE_IS_START_AS_DAEMON)) {
    if (config_->get(AttrName::SERVICE_IS_START_AS_DAEMON)->isString()) {
      is_start_as_daemon_ =
          (config_->string(AttrName::SERVICE_IS_START_AS_DAEMON)->get() ==
           "true");
    } else {
      is_start_as_daemon_ =
          config_->boolean(AttrName::SERVICE_IS_START_AS_DAEMON)->get();
    }
  }
  if (config_->has(AttrName::HTTP_HTTP_MAX_CALL_TIMEOUT)) {
    http_max_call_timeout_ =
        config_->getInt32(AttrName::HTTP_HTTP_MAX_CALL_TIMEOUT);
    if (http_max_call_timeout_ <= 0) {
      if (box_) {
        box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                        AttrName::HTTP_HTTP_MAX_CALL_TIMEOUT);
      }
      return false;
    }
  }
  if (config_->has(AttrName::STATISTICS_IS_OPEN_RPC_STAT)) {
    if (config_->get(AttrName::STATISTICS_IS_OPEN_RPC_STAT)->isString()) {
      is_open_rpc_stat_ =
          (config_->string(AttrName::STATISTICS_IS_OPEN_RPC_STAT)->get() ==
           "true");
    } else {
      is_open_rpc_stat_ =
          config_->boolean(AttrName::STATISTICS_IS_OPEN_RPC_STAT)->get();
    }
  }
  if (config_->has(AttrName::OPEN_TRACE)) {
    if (config_->get(AttrName::OPEN_TRACE)->isString()) {
      is_open_trace_ = (config_->string(AttrName::OPEN_TRACE)->get() == "true");
    } else {
      is_open_trace_ = config_->boolean(AttrName::OPEN_TRACE)->get();
    }
  }
  if (config_->has(AttrName::MODULE_MODULE_DIR)) {
    module_dir_ = config_->string(AttrName::MODULE_MODULE_DIR)->get();
  }
  if (config_->has(AttrName::LIMIT)) {
    if (!load_limit_config()) {
      return false;
    }
  }
  if (config_->has(AttrName::SERVICE_FINDER_VERSION)) {
    version_ = config_->string(AttrName::SERVICE_FINDER_VERSION)->get();
  }
  if (config_->has(AttrName::OPEN_RPC_TIMEOUT)) {
    is_open_rpc_timeout_ = config_->boolean(AttrName::OPEN_RPC_TIMEOUT)->get();
  }
  return true;
}

auto BoxConfigImpl::reload(const std::string &config_file_path,
                           std::string &error) -> bool {
  BoxConfigImpl new_box_config(box_);
  if (!new_box_config.load(config_file_path, error)) {
    return false;
  }
  // 调用事件监听器
  call_reload_listener(new_box_config);
  *this = std::move(new_box_config);
  return true;
}

auto BoxConfigImpl::add_reload_listener(const std::string &name,
                                        ReloadListener listener) -> bool {
  reload_listener_map_[name] = listener;
  return true;
}

auto BoxConfigImpl::remove_reload_listener(const std::string &name) -> bool {
  reload_listener_map_.erase(name);
  return true;
}

auto BoxConfigImpl::get_config_ptr() -> kconfig::Config * {
  return config_.get();
}

auto BoxConfigImpl::get_listener_list() const
    -> const std::vector<std::string> & {
  return listener_list_;
}

auto BoxConfigImpl::get_service_finder_type() const -> const std::string & {
  return finder_type_;
}

auto BoxConfigImpl::get_service_finder_hosts() const -> const std::string & {
  return finder_hosts_;
}

auto BoxConfigImpl::get_service_finder_connect_timeout() const -> std::time_t {
  return service_finder_connect_timeout_;
}

auto BoxConfigImpl::set_service_finder_connect_timeout(
    std::time_t timeout) const -> void {
  auto *mutable_this = const_cast<BoxConfigImpl *>(this);
  mutable_this->service_finder_connect_timeout_ = timeout;
  mutable_this->call_reload_listener(*this);
}

auto BoxConfigImpl::get_necessary_service() const
    -> const std::vector<std::string> & {
  return necessary_service_;
}

auto BoxConfigImpl::get_connect_other_box_timeout() const -> int {
  return connect_other_box_timeout_;
}

auto BoxConfigImpl::get_box_channel_recv_buffer_len() const -> int {
  return box_channel_recv_buffer_len_;
}

auto BoxConfigImpl::get_box_name() const -> const std::string & {
  return box_name_;
}

auto BoxConfigImpl::get_logger_config_line() const -> const std::string & {
  return logger_config_line_;
}

auto BoxConfigImpl::get_service_dir() const -> const std::string & {
  return service_dir_;
}

auto BoxConfigImpl::get_preload_service() const
    -> const std::unordered_map<std::string, std::string> & {
  return service_map_;
}

auto BoxConfigImpl::is_open_coroutine() const -> bool {
  return is_open_coroutine_;
}

auto BoxConfigImpl::is_lock_config() -> bool { return is_lock_config_; }

auto BoxConfigImpl::get_remote_service_repo_version_api() const
    -> const std::string & {
  return remote_service_repo_version_api_;
}

auto BoxConfigImpl::get_remote_service_repo_dir() const -> const std::string & {
  return remote_service_repo_dir_;
}

auto BoxConfigImpl::get_remote_service_repo_latest_version_api() const
    -> const std::string & {
  return remote_service_repo_latest_version_api_;
}

auto BoxConfigImpl::is_open_remote_update() const -> bool {
  return is_open_remote_update_;
}

auto BoxConfigImpl::get_remote_repo_check_interval() const -> int {
  return remote_repo_check_interval_;
}

auto BoxConfigImpl::is_start_as_daemon() const -> bool {
  return is_start_as_daemon_;
}

auto BoxConfigImpl::get_http_max_call_timeout() const -> int {
  return http_max_call_timeout_;
}

auto BoxConfigImpl::is_open_rpc_stat() -> bool { return is_open_rpc_stat_; }

auto BoxConfigImpl::is_open_trace() -> bool { return is_open_trace_; }

auto BoxConfigImpl::get_module_dir() -> const std::string & {
  return module_dir_;
}

auto BoxConfigImpl::get_version() -> const std::string & { return version_; }

auto BoxConfigImpl::is_open_rpc_timeout() -> bool {
  return is_open_rpc_timeout_;
}

auto BoxConfigImpl::has_attribute(const std::string &name) -> bool {
  return config_->has(name);
}

auto BoxConfigImpl::get_config_file_path() const -> const std::string & {
  return config_file_path_;
}

auto BoxConfigImpl::set_service_finder_connect_timeout(int timeout) -> void {
  service_finder_connect_timeout_ = timeout;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_connect_other_box_timeout(int timeout) -> void {
  connect_other_box_timeout_ = timeout;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_box_channel_recv_buffer_len(int len) -> void {
  box_channel_recv_buffer_len_ = len;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_http_max_call_timeout(int timeout) -> void {
  http_max_call_timeout_ = timeout;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_is_open_remote_update(bool on_off) -> void {
  is_open_remote_update_ = on_off;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_is_open_rpc_stat(bool value) -> void {
  is_open_rpc_stat_ = value;
  call_reload_listener(*this);
}

auto BoxConfigImpl::set_remote_repo_check_interval(int second) -> void {
  remote_repo_check_interval_ = second;
  call_reload_listener(*this);
}

auto BoxConfigImpl::get_listener_host_type() -> const std::string & {
  return listener_host_type_;
}

auto BoxConfigImpl::is_open_limit() -> bool { return is_open_limit_; }

auto BoxConfigImpl::get_limit_config() -> const LimitConfigVector & {
  return limit_config_vec_;
}

auto BoxConfigImpl::is_auto_load_service() -> bool {
  return is_auto_load_service_;
}

auto BoxConfigImpl::get_uuid_by_service_name(const std::string &service_name)
    -> const std::string & {
  static std::string NullString;
  for (const auto &[uuid, name] : service_map_) {
    if (name == service_name) {
      return uuid;
    }
  }
  return NullString;
}

auto BoxConfigImpl::copy_attribute(const BoxConfigImpl &rht) -> void {
  listener_list_ = rht.listener_list_;
  finder_type_ = rht.finder_type_;
  finder_hosts_ = rht.finder_hosts_;
  service_finder_connect_timeout_ = rht.service_finder_connect_timeout_;
  necessary_service_ = rht.necessary_service_;
  connect_other_box_timeout_ = rht.connect_other_box_timeout_;
  box_channel_recv_buffer_len_ = rht.box_channel_recv_buffer_len_;
  box_name_ = rht.box_name_;
  logger_config_line_ = rht.logger_config_line_;
  service_dir_ = rht.service_dir_;
  service_map_ = rht.service_map_;
  is_open_coroutine_ = rht.is_open_coroutine_;
  remote_service_repo_version_api_ = rht.remote_service_repo_version_api_;
  remote_service_repo_latest_version_api_ =
      rht.remote_service_repo_latest_version_api_;
  remote_service_repo_dir_ = rht.remote_service_repo_dir_;
  is_open_remote_update_ = rht.is_open_remote_update_;
  remote_repo_check_interval_ = rht.remote_repo_check_interval_;
  is_start_as_daemon_ = rht.is_start_as_daemon_;
  http_max_call_timeout_ = rht.http_max_call_timeout_;
  is_open_rpc_stat_ = rht.is_open_rpc_stat_;
}

auto BoxConfigImpl::load_limit_config() -> bool {
  if (config_->has(AttrName::LIMIT_OPEN_LIMIT)) {
    if (config_->get(AttrName::LIMIT_OPEN_LIMIT)->isString()) {
      is_open_limit_ =
          (config_->string(AttrName::LIMIT_OPEN_LIMIT)->get() == "true");
    } else {
      is_open_limit_ = config_->boolean(AttrName::LIMIT_OPEN_LIMIT)->get();
    }
  }
  auto *zone_ptr = config_->get(AttrName::LIMIT)->zone();
  while (zone_ptr->hasNext()) {
    auto *attr_ptr = zone_ptr->next();
    if (attr_ptr->isZone()) {
      LimitConfig limit_config;
      limit_config.service_name = attr_ptr->zone()->name();
      limit_config.uuid =
          get_uuid_by_service_name(limit_config.service_name + ".so");
      if (limit_config.uuid.empty()) {
        box_->write_log(
            lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
            std::string("limit." + limit_config.service_name).c_str());
        return false;
      }
      auto *limit_zone_ptr = attr_ptr->zone();
      if (limit_zone_ptr->has("bucket_volume")) {
        limit_config.bucket_volume =
            limit_zone_ptr->get("bucket_volume")->number()->getULlong();
      }
      if (limit_zone_ptr->has("token_per_sec")) {
        limit_config.token_per_sec =
            limit_zone_ptr->get("token_per_sec")->number()->getULlong();
      }
      if (limit_zone_ptr->has("type")) {
        limit_config.type = limit_zone_ptr->get("type")->string()->get();
      }
      if (0 == limit_config.bucket_volume) {
        limit_config.bucket_volume = limit_config.token_per_sec;
      }
      if (0 == limit_config.token_per_sec) {
        limit_config.token_per_sec = limit_config.bucket_volume;
      }
      if (0 == limit_config.bucket_volume && 0 == limit_config.token_per_sec) {
        box_->write_log(
            lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
            std::string("limit." + limit_config.service_name).c_str());
        return false;
      }
      limit_config_vec_.emplace_back(std::move(limit_config));
    }
  }
  return true;
}

auto BoxConfigImpl::find_all_services() -> void {
#ifndef DISABLE_SB_CODE
  std::vector<std::string> files;
  if (!util::get_file_in_directory(service_dir_, ".so", files)) {
    box_->write_log(
        lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
        std::string("Service directory not found [" + service_dir_ + "]")
            .c_str());
    return;
  }
  for (const auto &path : files) {
    util::ModuleLoader loader(nullptr);
    if (!loader.load(path)) {
      // 加载失败
      box_->write_log(lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
                      std::string("Service not found [" + path + "]").c_str());
    } else {
      // 获取UUID
      auto func = (rpc::BundleRegisterFunc)loader.get_export_func("onRegister");
      if (!func) {
        box_->write_log(
            lang::LangID::LANG_CONFIG_ERROR, klogger::Logger::FATAL,
            std::string("Service onRegister entry not found [" + path + "]")
                .c_str());
      } else {
        auto uuid = func(nullptr);
        // 放入预加载表
        service_map_[std::to_string(uuid)] =
            std::filesystem::path(path).filename().string();
      }
    }
  }
#endif
}

auto BoxConfigImpl::operator=(BoxConfigImpl &&rht) noexcept
    -> const BoxConfigImpl & {
  listener_list_ = std::move(rht.listener_list_);
  finder_type_ = rht.finder_type_;
  finder_hosts_ = rht.finder_hosts_;
  service_finder_connect_timeout_ = rht.service_finder_connect_timeout_;
  necessary_service_ = std::move(rht.necessary_service_);
  connect_other_box_timeout_ = rht.connect_other_box_timeout_;
  config_ = std::move(rht.config_);
  box_channel_recv_buffer_len_ = rht.box_channel_recv_buffer_len_;
  box_name_ = std::move(rht.box_name_);
  logger_config_line_ = std::move(rht.logger_config_line_);
  service_dir_ = std::move(rht.service_dir_);
  service_map_ = std::move(rht.service_map_);
  is_open_coroutine_ = rht.is_open_coroutine_;
  remote_service_repo_version_api_ =
      std::move(rht.remote_service_repo_version_api_);
  remote_service_repo_latest_version_api_ =
      std::move(rht.remote_service_repo_latest_version_api_);
  remote_service_repo_dir_ = std::move(rht.remote_service_repo_dir_);
  is_open_remote_update_ = rht.is_open_remote_update_;
  remote_repo_check_interval_ = rht.remote_repo_check_interval_;
  is_start_as_daemon_ = rht.is_start_as_daemon_;
  http_max_call_timeout_ = rht.http_max_call_timeout_;
  is_open_rpc_stat_ = rht.is_open_rpc_stat_;
  // TODO 增补
  return *this;
}

auto BoxConfigImpl::call_reload_listener(const BoxConfigImpl &config) -> void {
  for (const auto &[name, method] : reload_listener_map_) {
    method(name, config);
  }
}

auto BoxConfigImpl::register_config_function() -> void {
  REG_FUNCTION(os_name);
  REG_FUNCTION(print);
  REG_FUNCTION(is_debug);
  REG_FUNCTION(is_release);
  REG_FUNCTION(cwd);
  REG_FUNCTION(bin_path);
  REG_FUNCTION(bin_name);
  REG_FUNCTION(exec);
  REG_FUNCTION(get_env);
}

auto BoxConfigImpl::register_config_variable() -> void {
  REG_ATTRIBUTE(K, std::make_shared<NumberImpl>("1024"));
  REG_ATTRIBUTE(M, std::make_shared<NumberImpl>("1048576"));
  REG_ATTRIBUTE(G, std::make_shared<NumberImpl>("1073741824"));
}

IMPL_FUNCTION(os_name) {
#if defined(WIN32) || defined(_WIN32) || defined(_WIN64)
  return std::make_shared<StringImpl>("windows");
#else
  return std::make_shared<StringImpl>("linux");
#endif
}

IMPL_FUNCTION(print) {
  for (const auto &arg_ptr : args) {
    std::cout << arg_ptr->to_string();
  }
  std::cout << std::endl;
  return std::make_shared<NullImpl>();
}

IMPL_FUNCTION(is_debug) {
#if defined(DEBUG) || defined(_DEBUG)
  return std::make_shared<BoolImpl>(true);
#else
  return std::make_shared<BoolImpl>(false);
#endif
}

IMPL_FUNCTION(is_release) {
#if defined(DEBUG) || defined(_DEBUG)
  return std::make_shared<BoolImpl>(false);
#else
  return std::make_shared<BoolImpl>(true);
#endif
}

IMPL_FUNCTION(cwd) {
  return std::make_shared<StringImpl>(
      std::filesystem::current_path().string().c_str());
}

IMPL_FUNCTION(bin_path) {
  return std::make_shared<StringImpl>(util::get_binary_path());
}

IMPL_FUNCTION(bin_name) {
  return std::make_shared<StringImpl>(util::get_binary_name());
}

IMPL_FUNCTION(exec) {
  std::string cmd_line;
  for (const auto &arg : args) {
    if (!arg->isString()) {
      return std::make_shared<NullImpl>();
    }
    cmd_line += " " + arg->to_string();
  }
  return std::make_shared<StringImpl>(util::execute(cmd_line));
}

IMPL_FUNCTION(get_env) {
  if (args.empty() || args.size() != 1 || !args[0]->isString()) {
    return std::make_shared<NullImpl>();
  }
  return std::make_shared<StringImpl>(util::get_env(args[0]->to_string()));
}

} // namespace config
} // namespace kratos
